/*
*   量程切换、参数范围限定
*   公式需要改进
*   已通过编译
*/
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "driver/gpio.h"
#include "driver/mcpwm.h"
#include "soc/mcpwm_periph.h"
#include "bsp_backlight.h"

static const char *TAG = "bsp_backlight";

static bool level;
static float duty_saved;
static bool backlight_status;

static void _bsp_backlight_gpio_init(void)
{
    ESP_LOGI(TAG, "initializing backlight gpio......");

    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << CONFIG_HUD_BL_GPIO) | (1ULL << CONFIG_HUD_BL_EN);
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    gpio_config(&io_conf);

    gpio_set_level(CONFIG_HUD_BL_GPIO, 0);
    gpio_set_level(CONFIG_HUD_BL_EN, 0);
    mcpwm_gpio_init(CONFIG_HUD_BL_UNIT, CONFIG_HUD_BL_SIGNAL, CONFIG_HUD_BL_GPIO); //Set GPIO 18 as PWM0A, to which servo is connected
}

static void _bsp_backlight_set_duty(float duty)
{
    duty = (duty > 100) ? 100 : (duty < 0) ? 0
                                           : duty;
    // ESP_LOGI(TAG, "set duty to %f", duty);
    duty_saved = duty;
    mcpwm_set_duty(CONFIG_HUD_BL_UNIT, CONFIG_HUD_BL_TIMER, MCPWM_OPR_A, duty);
    // printf("backlight duty:%f\n", duty_saved);
}

/**初始化背光**/
void bsp_backlight_init(void)
{
    level = 1;
    //初始化PWM_GPIO
    _bsp_backlight_gpio_init();

    //配置PWM参数
    ESP_LOGI(TAG, "Configuring Initial Parameters of pwm......");
    mcpwm_config_t pwm_config;
    pwm_config.frequency = CONFIG_HUD_BL_FREQ; //frequency = 50Hz, i.e. for every servo motor time period should be 20ms
    pwm_config.cmpr_a = 0;                     //duty cycle of PWMxA = 0
    pwm_config.cmpr_b = 0;                     //duty cycle of PWMxb = 0
    pwm_config.counter_mode = MCPWM_UP_COUNTER;
    pwm_config.duty_mode = MCPWM_DUTY_MODE_0;
    mcpwm_init(CONFIG_HUD_BL_UNIT, CONFIG_HUD_BL_TIMER, &pwm_config); //Configure PWM0A & PWM0B with above settings
    mcpwm_start(CONFIG_HUD_BL_UNIT, CONFIG_HUD_BL_TIMER);
    //初始关闭背光
    bsp_backlight_stop();
}

/**开启背光**/
void bsp_backlight_start(void)
{
    ESP_LOGI(TAG, "Turn on the backlight");
    backlight_status = 1;
    gpio_set_level(CONFIG_HUD_BL_EN, 1);
    _bsp_backlight_set_duty((float)duty_saved);
}

/**关闭背光**/
void bsp_backlight_stop(void)
{
    ESP_LOGI(TAG, "Turn off the backlight");
    backlight_status = 0;
    gpio_set_level(CONFIG_HUD_BL_EN, 0);
    _bsp_backlight_set_duty(0);
}

void bsp_backlight_set_duty(float duty)
{
    _bsp_backlight_set_duty(duty);
}

/* --重写 考虑各种情况--根据温度与环境光计算背光亮度 */
void bsp_backlight_calculate_set(float temp, float light, uint16_t brightness)
{
    //亮度判断，量程切换
    float duty;

    float temp_coe = (5 - 0.06 * temp);
    temp_coe = (temp_coe > 1) ? 1 : (temp_coe < 0) ? 0
                                                   : temp_coe; //限定温度系数范围

    if (level)
    {
        //低量程，亮度太低，切换到高量程
        if (light < CONFIG_HUD_BL_SLMIN)
        {
            ESP_LOGI(TAG, "switch to high");
            level = 0;
            gpio_set_level(GPIO_OUTPUT_IO, 0);
        }
        //io口量程切换
        duty = temp_coe * ((float)brightness + (light / 2.4 * (float)(1000 - brightness)));
    }
    else
    {
        //高量程，亮度太大
        if (light > CONFIG_HUD_BL_SLMAX)
        {
            ESP_LOGI(TAG, "switch to low");
            level = 1;
            gpio_set_level(GPIO_OUTPUT_IO, 1);
        }
        duty = temp_coe * ((float)brightness + (light / 47.52 * (float)(1000 - brightness)));
    }

    //平缓亮度变化
    _bsp_backlight_set_duty(duty);
}